from math import sqrt as sqrt
from gb_exceptions import *

class bezier_curve(object):
    def __init__(self):
        self.points=[]
        self.total_length = 0
        pass

    def length(self):
        """Returns actual (unparametrisized) length of curve"""
        return self.total_length

    def add_point(self,x,y):
        """Adds a point"""
        self.points.append((x,y))

    def set_point(self,point,x,y):
        self.points[point] = [x,y]
        self.__update_length()

    def __update_length(self):
        pass

    def get_position(self,t):
        """Gets unparametrisized position from parameter t"""
        pass


class linear_bezier(bezier_curve):
    """Simple Linear Bezier Curves - i.e. lines between points"""

    def add_point(self,x,y):
        self.points.append((x,y))
        self.__update_length()
    
    def __update_length(self):
        self.total_length = 0
        for i in range(len(self.points)-1):
            self.total_length += sqrt(
                    (self.points[i][0] - self.points[i+1][0])**2 + 
                    (self.points[i][1] - self.points[i+1][1])**2
                    )

    def get_position(self,t=0.):
        if float(t)> 1.:
            t = 1.
        
        # find which segment we're on
        i = 0
        length = 0.
        t_times_total = t*self.total_length
        while i < len(self.points):
            segment_length = sqrt(
                    (self.points[i][0] - self.points[i+1][0])**2 + 
                    (self.points[i][1] - self.points[i+1][1])**2
                    )
            if length + segment_length > t_times_total or (i+2 == len(self.points)):
                break
            else: 
                length += segment_length
            i+=1


        # should be at the segment starting with point i
        # find out how far along this segment we are
        dist = ( t_times_total - length ) / (segment_length)

        vector = (self.points[i+1][0] - self.points[i][0],
                    self.points[i+1][1] - self.points[i][1])
        
        return (self.points[i][0] + dist * vector[0],
                self.points[i][1] + dist * vector[1])
            

        
